package square;

import java.math.BigDecimal;
import java.util.ArrayList;

import be.kuleuven.cs.som.annotate.Basic;
import be.kuleuven.cs.som.annotate.Immutable;
import border.Border;
import border.Door;

/**
 * A class of transparent squares as special kinds of teleportation squares
 * involving as additional properties that all borders must be doors.
 * 
 * @version	3.0
 * @author 	Inge Gielis <inge.gielis@student.kuleuven.be>
 * @author	Annelies Ketelslegers <annelies.ketelslegers@student.kuleuven.be>
 *
 */

public class TransparentSquare extends TeleportationSquare {
	
	
	/**
	 * Initialize this new square with given temperature and given humidity
	 * and define the floor that will be attached to this square as slippery or not.
	 * 
	 * @param 	temperature
	 * 			The temperature for this new square.
	 * @param 	humidity
	 * 		  	The humidity for this new square.
	 * @param	direction
	 * 			The direction in which the new door must be 
	 * 			constructed.
	 * @post  	The new temperature for this new square is equal to
	 * 			the given temperature.
	 * 			| new.getTemperature() == temperature
	 * @post  	The new humidity of this new square is equal to the given humidity.
	 * 			| new.getHumidity() == humidity
	 * @post	A closed door is attached in the given direction
	 * 			| new.getBorder(direction).isClosed() == true
	 * @throws 	IllegalArgumentException 
	 * 			The given temperature is not a valid value
	 * 			| ! isValidTemperature(temperature)
	 */
	public TransparentSquare(Temperature temperature,BigDecimal humidity, Direction direction) 
		throws IllegalArgumentException{
		super(temperature, humidity);
		new Door(this,direction, true);
	}
	
	/**
	 * Return the lower limit of the temperature that applies to all transparent squares.
	 * 		The lower limit of the temperature expresses the lowest possible value
	 * 		for the temperature of a transparent square.
	 */
	@Basic @Immutable
	@Override
	public Temperature getMinTemperature(){
		return MIN_TEMPERATURE;
	}
	
	/**
	 * Return the upper limit for the temperature that applies to all transparent squares.
	 * 		The upper limit of the temperature expresses the highest possible value
	 * 		for the temperature of a transparent square.
	 */
	@Basic @Immutable
	@Override
	public Temperature getMaxTemperature(){
		return MAX_TEMPERATURE;
	}

	/**
	 * Variable registering the upper limit for the temperature that applies to all transparent squares.
	 */
	private static final Temperature MAX_TEMPERATURE = new Temperature(5000,TemperatureScale.CELCIUS);

	/**
	 * Variable registering the lower limit for the temperature that applies to all transparent squares.
	 */
	private final static Temperature MIN_TEMPERATURE = new Temperature(-200,TemperatureScale.CELCIUS);
	
	/**
	 * Return the maximum amount of doors that a transparent square can have.
	 */
	@Override
	public int getMaxNbDoors() {
		return MAX_NB_DOORS;
	}

	/**
	 * Variable registering the maximum amount of doors a transparent square can have.
	 */
	private final static int MAX_NB_DOORS = 2;

	/**
	 * Return the maximum amount of borders that a transparent square can have.
	 */
	@Override
	public int getMaxNbBorders(){
		return MAX_NB_DOORS;
	}

	/**
	 * Check whether this transparent square can have the given border as its border.
	 * 
	 *@return 	True if and only if the given border is effective
	 * 			and if the given border is not terminated 
	 * 			and if the given border references this rock as one of its squares
	 * 			and if the given border is a door.
	 * 			| result == border != null && ! border.isTerminated() 
	 * 			|		&& border.hasAsSquare(this) && border instanceof Door
	 */
	@Override
	public boolean canHaveAsBorder(Border border) {
		return super.canHaveAsBorder(border) && (border instanceof Door);
	}

	/**
	 * Check whether this transparent square has proper borders attached to it.
	 * 
	 *@return	False if this method defined at the level of the superclass, is false.
	 *			|if(! super.hasProperBorders())
	 *			|	then result == false
	 *@return	If the number of borders equals 2, true if those 2 borders are on opposite sides.
	 *			| if(getNbBorders() == 2)
	 *			|	then result == getBorders().get(0).getOpposite().equals(getBorders().get(1))
	 */
	@Override
	public boolean hasProperBorders() {
		if(! super.hasProperBorders())
			return false;
		if(getNbBorders() == 2){
			ArrayList<Direction> borderdirections = new ArrayList<Direction>(getBorders().keySet());
			return borderdirections.get(0).getOpposite().equals(borderdirections.get(1));}
		return true;
	}

	/**
	 * Check whether a border can be attached to this transparent square
	 * in the given direction.
	 * 
	 * @return	False if the given direction is not effective or if
	 * 			there already is a border attached to this transparent square 
	 * 			in the given direction.
	 * 			|if(direction == null || getBorder(direction) != null
	 * 			|	result == false
	 * @return	Otherwise, if there is no border attached yet, return true.
	 * 			|if(getNbBorders() == 0)
	 * 			|	result == true
	 * @return	Otherwise, there will be one border attached to this square
	 * 			(due to the precondition)
	 * 			|	result == getBorder(direction.getOpposite())!= null
	 * 			
	 */
	@Override
	protected boolean canAttachBorderInDirection(Direction direction){
		//For this type of squares, there can be at most 1 border attached to this square yet.
		if(! super.canAttachBorderInDirection(direction))
			return false;
		if(getNbBorders() == 0)
			return true;
		return getBorder(direction.getOpposite())!= null;		
	}


}
